﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using UBCon.Core.Enums;

namespace UBCon.Ribbon.SkinManagers
{
    public static class SkinManager
    {
        //------------------------------------------------------
        //
        //  Properties
        //
        //------------------------------------------------------
        #region Properties


        /// <summary>
        /// Gets Office2007 skin ResourceDictionary.
        /// </summary>
        internal static Office2007SkinManager Office2007Skin
        {
            get
            {
                if (office2007Skin == null)
                {
                    office2007Skin = new Office2007SkinManager();

                }

                return office2007Skin;
            }
        }

        /// <summary>
        /// Gets Office2010 skin ResourceDictionary.
        /// </summary>
        internal static Office2010SkinManager Office2010Skin
        {
            get
            {
                if (office2010Skin == null)
                {
                    office2010Skin = new Office2010SkinManager();
                }

                return office2010Skin;
            }
        }


        /// <summary>
        /// Gets blue theme ResourceDictionary.
        /// </summary>
        internal static ResourceDictionary OfficeBlueTheme
        {
            get
            {
                if (officeBlueTheme == null)
                {
                    officeBlueTheme = new ResourceDictionary()
                    {
                        Source = new Uri(StringConstants.OfficeBlueThemeName, UriKind.Relative)
                    };
                }
                return officeBlueTheme;
            }
        }

        /// <summary>
        /// Gets blue skin ResourceDictionary.
        /// </summary>
        internal static ResourceDictionary OfficeBlueSkin
        {
            get
            {
                if (officeBlueSkin == null)
                {
                    officeBlueSkin = new ResourceDictionary()
                    {
                        Source = new Uri(StringConstants.OfficeBlueSkinName, UriKind.Relative)
                    };
                }
                return officeBlueSkin;
            }
        }

        /// <summary>
        /// Gets green skin ResourceDictionary.
        /// </summary>
        internal static ResourceDictionary OfficeGreenSkin
        {
            get
            {
                if (officeGreenSkin == null)
                {
                    officeGreenSkin = new ResourceDictionary()
                    {
                        Source = new Uri(StringConstants.OfficeGreenSkinName, UriKind.Relative)
                    };
                }
                return officeGreenSkin;
            }
        }

        internal static ResourceDictionary DarkSkin
        {
            get
            {
                if (darkSkin == null)
                {
                    darkSkin = new ResourceDictionary
                    {
                        Source = new Uri(StringConstants.DarkSkinName, UriKind.Relative)
                    };
                }

                return darkSkin;
            }
        }

    



        /// <summary>
        /// Gets red skin ResourceDictionary.
        /// </summary>
        internal static ResourceDictionary OfficeRedSkin
        {
            get
            {
                if (officeRedSkin == null)
                {
                    officeRedSkin = new ResourceDictionary()
                    {
                        Source = new Uri(StringConstants.OfficeRedSkinName, UriKind.Relative)
                    };
                }
                return officeRedSkin;
            }
        }

        /// <summary>
        /// Gets violet skin ResourceDictionary.
        /// </summary>
        internal static ResourceDictionary OfficeVioletSkin
        {
            get
            {
                if (officeVioletSkin == null)
                {
                    officeVioletSkin = new ResourceDictionary()
                    {
                        Source = new Uri(StringConstants.OfficeVioletSkinName, UriKind.Relative)
                    };
                }

                return officeVioletSkin;
            }
        }

        /// <summary>
        /// Gets darkred skin ResourceDictionary.
        /// </summary>
        internal static ResourceDictionary OfficeDarkRedSkin
        {
            get
            {
                if (officeDarkRedSkin == null)
                {
                    officeDarkRedSkin = new ResourceDictionary()
                    {
                        Source = new Uri(StringConstants.OfficeDarkRedSkinName, UriKind.Relative)
                    };
                }
                return officeDarkRedSkin;
            }
        }

        /// <summary>
        /// Gets the value of the UBCon.Ribbon.SkinManager.Skin attached property for the 
        /// given dependency object.
        /// </summary>
        public static Skin GetSkin(DependencyObject obj)
        {
            return (Skin)obj.GetValue(SkinProperty);
        }

        /// <summary>
        /// Sets the value of the UBCon.Ribbon.SkinManager.Skin attached property for the 
        /// given dependency object.
        /// </summary>
        public static void SetSkin(DependencyObject obj, Skin value)
        {
            obj.SetValue(SkinProperty, value);
        }

        /// <summary>
        /// Identifies UBCon.Ribbon.SkinManager.Skin attached property.
        /// </summary>
        public static readonly DependencyProperty SkinProperty =
            DependencyProperty.RegisterAttached("Skin", typeof(Skin), typeof(SkinManager), 
            new FrameworkPropertyMetadata(Skin.OfficeBlue, new PropertyChangedCallback(SkinManager.OnSkinPropertyChanged)));

        /// <summary>
        /// Gets the value of the UBCon.Ribbon.SkinManager.EnableCustomStyling attached property for the 
        /// given dependency object.
        /// </summary>
        public static bool GetEnableCustomStyling(DependencyObject obj)
        {
            return (bool)obj.GetValue(EnableCustomStylingProperty);
        }

        /// <summary>
        /// Sets the value of the UBCon.Ribbon.SkinManager.EnableCustomStyling attached property for the 
        /// given dependency object.
        /// </summary>
        public static void SetEnableCustomStyling(DependencyObject obj, bool value)
        {
            obj.SetValue(EnableCustomStylingProperty, value);
        }

        /// <summary>
        /// Identifies UBCon.Ribbon.SkinManager.EnableCustomStyling attached property.
        /// </summary>
        internal static readonly DependencyProperty EnableCustomStylingProperty =
            DependencyProperty.RegisterAttached("EnableCustomStyling", typeof(bool), typeof(SkinManager), new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnEnableCustomStylingPropertyChanged)));
        #endregion

        //------------------------------------------------------
        //
        //  Depenency Property Changed Callbacks
        //
        //------------------------------------------------------
        #region Depenency Property Changed Callbacks
        /// <summary>
        /// Invoked whenever EnableCustomStyling attached property changes. 
        /// </summary>
        /// <param name="sender">Type: System.Windows.DependencyObject. The DependencyObject on which the property has changed value.</param>
        /// <param name="e">Type: System.Windows.DependencyPropertyChangedEventArgs. Event data that is issued by any event that tracks changes to the effective value of this property.</param>
        private static void OnEnableCustomStylingPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) 
        {
            ScrollViewer scroller = sender as ScrollViewer;

            if (scroller == null) 
            {
                return;
            }

            if (!(bool)e.NewValue) 
            {
                scroller.ClearValue(ScrollViewer.StyleProperty);
                return;
            }
            if ((bool)e.NewValue) 
            {
                Style style = RibbonHelper.GetResourceByKey<Style>("ScrollViewerStyle");

                if (style != null) 
                {
                    scroller.SetValue(ScrollViewer.StyleProperty, style);
                }
            }
        }


        /// <summary>
        /// Invoked whenever Skin attached property changes. 
        /// </summary>
        /// <param name="sender">Type: System.Windows.DependencyObject. The DependencyObject on which the property has changed value.</param>
        /// <param name="e">Type: System.Windows.DependencyPropertyChangedEventArgs. Event data that is issued by any event that tracks changes to the effective value of this property.</param>
        private static void OnSkinPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) 
        {
            FrameworkElement elt = sender as FrameworkElement;
           
            if (elt != null) 
            {
                ChangeSkin(elt, (Skin)e.NewValue);
            }
        }
        #endregion

        //------------------------------------------------------
        //
        //  Internal Methods
        //
        //------------------------------------------------------
        #region Internal methods

        /// <summary>
        /// Gets ResourceDictionary with specified skin.
        /// </summary>
        /// <param name="skin">Type: UBCon.Core.Enums.Skin. A Skin value to find.</param>
        /// <returns>Type: System.Windows.ResourceDictionary. </returns>
        internal static ResourceDictionary GetResource(Skin skin)
        {
            ResourceDictionary dictionary = null;

            switch (skin)
            {
                case Skin.OfficeGreen:

                    dictionary = OfficeGreenSkin;

                    break;

                case Skin.OfficeRed:

                    dictionary = OfficeRedSkin;

                    break;

                case Skin.OfficeDarkRed:

                    dictionary = OfficeDarkRedSkin;

                    break;

                case Skin.OfficeViolet:

                    dictionary = OfficeVioletSkin;
                    break;

                case Skin.Dark:

                    dictionary = DarkSkin;

                    break;
            }
            return dictionary;
        }

        /// <summary>
        /// Changes specified FrameworkElement's skin.
        /// </summary>
        /// <param name="elt">Type: System.Windows.FrameworkElement. A control of which skin is changed.</param>
        /// <param name="skin">Type: UBCon.Core.Enums.Skin. A skin which is applied to specified FrameworkElement.</param>
        internal static void ChangeSkin(FrameworkElement elt, Skin skin)
        {
            elt.Resources.MergedDictionaries.Clear();

            if (skin == Skin.Office2010)
            {
                elt.Resources.MergedDictionaries.Clear();

                if (Office2010Skin.ColorResources != null)
                {
                    elt.Resources.MergedDictionaries.Add(Office2010Skin.ColorResources);
                }

                if (Office2010Skin.RibbonChrome != null)
                {
                    elt.Resources.MergedDictionaries.Add(Office2010Skin.RibbonChrome);
                }

            }

            else 
            {
                if (skin != Skin.OfficeBlue)
                {
                    ResourceDictionary res = SkinManagers.SkinManager.GetResource(skin);
                    if (res != null)
                    {
                        elt.Resources.MergedDictionaries.Add(res);
                    }
                }
            }
        }

        /// <summary>
        /// Changes specific control's or application's into Office2010 skin.
        /// </summary>
        internal static void ChangeTo2010()
        {
            Application.Current.Resources.MergedDictionaries.Clear();

            Application.Current.Resources.MergedDictionaries.Add(Office2010Skin.ColorResources);

            Application.Current.Resources.MergedDictionaries.Add(Office2010Skin.ApplicationMenu);

            Application.Current.Resources.MergedDictionaries.Add(Office2010Skin.RibbonChrome);

            Application.Current.Resources.MergedDictionaries.Add(Office2010Skin.RibbonWindow);

           // Application.Current.Resources.MergedDictionaries.Add(Office2010Skin.RibbonTabItem);

            
        }

        /// <summary>
        /// Changes specific control's or application's into Office2010 skin.
        /// </summary>
        internal static void ChangeTo2007()
        {
            Application.Current.Resources.MergedDictionaries.Clear();

            if (Office2007Skin != null) 
            {
                if (Office2007Skin.RibbonChrome != null)
                {
                    Application.Current.Resources.MergedDictionaries.Add(Office2007Skin.RibbonChrome);
                }
                
                if (Office2007Skin.ColorResources != null)
                {
                    Application.Current.Resources.MergedDictionaries.Add(Office2007Skin.ColorResources);
                }

                if (Office2007Skin.RibbonButton != null) 
                {
                    Application.Current.Resources.MergedDictionaries.Add(Office2007Skin.RibbonButton);
                }

                if (Office2007Skin.RibbonBar != null)
                {
                    Application.Current.Resources.MergedDictionaries.Add(Office2007Skin.RibbonBar);
                }

                if (Office2007Skin.RibbonTabItem != null)
                {
                    Application.Current.Resources.MergedDictionaries.Add(Office2007Skin.RibbonTabItem);
                }
                if (Office2007Skin.RibbonWindow != null)
                {
                    Application.Current.Resources.MergedDictionaries.Add(Office2007Skin.RibbonWindow);
                }
                if (Office2007Skin.ApplicationMenu != null)
                {
                    Application.Current.Resources.MergedDictionaries.Add(Office2007Skin.ApplicationMenu);
                }
            }
        }

        /// <summary>
        /// Changes theme at application level.
        /// </summary>
        /// <param name="skin">Specified skin into which application's theme is changed.</param>
        public static void ChangeAppSkin(Skin skin)
        {
            Application.Current.Resources.MergedDictionaries.Clear();

            if (skin == Skin.Office2010)
            {
                ChangeTo2010();
            }
            else if (skin == Skin.Office2007) 
            {
                ChangeTo2007();
            }
            else
            {
                if (skin != Skin.OfficeBlue)
                {
                    ResourceDictionary res = SkinManagers.SkinManager.GetResource(skin);
                    if (res != null)
                    {
                        Application.Current.Resources.MergedDictionaries.Add(res);
                    }
                }
            }

        }

        #endregion

        //------------------------------------------------------
        //
        //  Fields
        //
        //------------------------------------------------------
        #region Fields

        private static ResourceDictionary officeBlueSkin, 
                                            officeBlueTheme, 
                                            officeGreenSkin, 
                                            officeRedSkin, 
                                            officeVioletSkin, 
                                            officeDarkRedSkin,
                                            darkSkin;

        private static Office2010SkinManager office2010Skin;

        private static Office2007SkinManager office2007Skin;

        
        #endregion

    }

}
